
#include "PipelineInfo.h"

#ifdef TTG_PL_VISUALIZER

#include <algorithm>

using namespace ttg;
using namespace ttg::structures;
using namespace ttg::extras;
using namespace ttg::threads;
using namespace ttg_internal::pipeline;

//--------------------
//--- PipelineInfo ---
//--------------------

PipelineInfo::PipelineInfo()
	:NamedObject("UNNAMED_FIXME")
{
	nodes_filter = new ttg::utils::ParameterSet(
		"UNNAMED_FIXME", ttg::utils::UtilManager::getRef()->getInternalSets()->getPipelines());
	sub_pipelines_filter = new ttg::utils::ParameterSet("Sub pipelines", nodes_filter);
	//Nodes
	this->starttime = 0.0f;
	this->frametime = 0.0f;
	this->summedtime = 0.0f;
	this->nodes_cs = NULL;
	this->is_independent = true;
}

PipelineInfo::PipelineInfo(const char *name,
						   std::vector<ttg_internal::pipeline::NavigatorNode *> &nodes,
						   CriticalSection *nodes_cs)
	:NamedObject(name)
{
	nodes_filter = new ttg::utils::ParameterSet(
		name, ttg::utils::UtilManager::getRef()->getInternalSets()->getPipelines());
	sub_pipelines_filter = new ttg::utils::ParameterSet("Sub pipelines", nodes_filter);
	//Nodes
	this->nodes.resize(nodes.size());
	for (size_t i = 0; i < nodes.size(); i++)
		this->nodes[i] = &nodes[i]->getInfo();
	this->starttime = 0.0f;
	this->frametime = 0.0f;
	this->summedtime = 0.0f;
	this->nodes_cs = nodes_cs;
	this->is_independent = false;
}

void PipelineInfo::update(double starttime, double frametime,
						  const std::vector<PerformerInfo *> &performers)
{
	this->starttime = starttime;
	this->frametime = frametime;
	summedtime = 0.0f;
	for (size_t i = 0; i < nodes.size(); i++)
	{ summedtime += nodes[i]->getTimeDifficulty(); }
	this->performers = performers;
}

PipelineInfo::~PipelineInfo()
{
	SAFE_DELETE(sub_pipelines_filter);
	SAFE_DELETE(nodes_filter);
	if (is_independent)
	{
		SAFE_DELETE_CONTENT(&nodes);
		SAFE_DELETE_CONTENT(&performers);
		SAFE_DELETE(this->nodes_cs);
	}
	nodes.clear();
	performers.clear();
}

PipelineInfo *PipelineInfo::create(XMLTree &xml)
{
	PipelineInfo *res = new PipelineInfo();
	//Common
	if (!xml.getDoubleAttribute("starttime", res->starttime) ||
		!xml.getDoubleAttribute("frametime", res->frametime) ||
		!xml.getDoubleAttribute("summedtime", res->summedtime))
	{
		delete res;
		ttg::services::addLocalError("PipelineInfo", "create", "Cannot find attribute");
		return NULL;
	}
	//Nodes
	Dictionary<NodeInfo> *nodes;
	xml.openSection("Nodes");
	{
		nodes = NodeInfo::create(xml.getSubXMLTree());
	} xml.closeSection();
	//Performers
	xml.openSection("Performers");
	{
		xml.resetIterators();
		while (xml.openNextSection())
		{
			PerformerInfo *p = PerformerInfo::create(xml.getSubXMLTree());
			if (p == NULL)
			{
				delete res;
				return NULL;
			}
			res->performers.push_back(p);
			xml.closeSection();
		}
	} xml.closeSection();
	//Finishing
	ttg::structures::EnumerableCollection<NodeInfo *> *ec = nodes->removeAll();
	res->nodes = ec->toVector();
	SAFE_DELETE(ec);
	delete nodes;
	res->nodes_cs = new SlowCriticalSection();
	return res;
}

void PipelineInfo::store(XMLTree &xml, PipelineInfo *val)
{
	xml.addSectionAndOpen("Pipeline");
	{
		//Adding common.
		xml.addDoubleAttribute("starttime", val->starttime);
		xml.addDoubleAttribute("frametime", val->frametime);
		xml.addDoubleAttribute("summedtime", val->summedtime);
		xml.addIntAttribute("threadcount", (int)val->performers.size());		//for compatibility
		//Adding nodes
		NodeInfo::store(xml.getSubXMLTree(), StlEnumerator<NodeInfo *, std::vector<NodeInfo *>::iterator>
													(val->nodes.begin(), val->nodes.end()));
		//Adding performers
		xml.addSectionAndOpen("Performers");
		{
			if (val->performers.size() != 0)
				for (size_t i = 0; i < val->performers.size(); i++)
				{
					val->performers[i]->store(xml.getSubXMLTree());
				}
			else
				xml.addStringAttribute("stub", "TODO: fix me");
		} xml.closeSection();
	} xml.closeSection();
}

#endif
